package fido;

import fido.torrentsite.CookiedTorrentSite;
import fido.torrentsite.TorrentSite;
import org.apache.log4j.Logger;
import org.mymediadb.api.mmdb.model.Movie;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * Created by IntelliJ IDEA.
 * User: Anders
 * Date: 20.07.11
 * Time: 05:03
 */
public final class TorrentSites {
    private static final Logger LOG = Logger.getLogger(Main.class);

    private List<TorrentSite> torrentSites;
    private List<TorrentSite> selectedTorrentSites;
    private static TorrentSites torrentSitesInstance = null;

    public static TorrentSites instance() {
        if (torrentSitesInstance == null) {
            torrentSitesInstance = new TorrentSites();
        }
        return torrentSitesInstance;
    }

    private TorrentSite getTorrentSite(String torrentSiteAlias) {
        for (TorrentSite torrentSite : torrentSites ) {
            if (torrentSite.getTorrentSiteAlias().equals(torrentSiteAlias)) {
                return torrentSite;
            }
        }
        return null;
    }

    private TorrentSites() {
        setupAllTorrentSiteObjects();
        selectedTorrentSites = new ArrayList<TorrentSite>();
    }

    public boolean torrentSiteExists(String torrentSiteAlias) {
        for (TorrentSite torrentSite : torrentSites) {
            if (torrentSiteAlias.equals(torrentSite.getTorrentSiteAlias())) {
                return true;
            }
        }
        return false;
    }


    private void setupAllTorrentSiteObjects() {
        torrentSites = new ArrayList<TorrentSite>();
        List<Class> torrentSitesClasses = getAllTorrentSiteClasses();
        for (Class torrentSiteClass : torrentSitesClasses) {

            try {
                TorrentSite torrentSite = (TorrentSite) Class.forName(torrentSiteClass.getCanonicalName()).newInstance();
                torrentSites.add(torrentSite);
            } catch (InstantiationException e) {
                LOG.error(e.getMessage());
            } catch (IllegalAccessException e) {
                LOG.error(e.getMessage());
            } catch (ClassNotFoundException e) {
                LOG.error(e.getMessage());
            }
        }
    }

    private List<Class> getAllTorrentSiteClasses() {

        List<Class> torrentSitesClasses = new ArrayList<Class>();

        Class<? extends TorrentSite>[] classList = ClassDiscovery.DiscoverClasses(TorrentSite.class, null, TorrentSite.class);
        for (Class<? extends TorrentSite> aClass : classList) {
            if (aClass.equals(TorrentSite.class) || aClass.equals(CookiedTorrentSite.class)) {
                continue;
            }
            if (TorrentSite.class.isAssignableFrom(aClass)) {
                torrentSitesClasses.add(aClass);
            }

        }
        return torrentSitesClasses;
    }

    /**
     * Selects all torrentsites found in the torrentSiteAlias string
     *
     * @param torrentSiteAliases Create an instance of the class with this name
     */
    public void select(String torrentSiteAliases) {
        if (!isSelected(torrentSiteAliases)) {
            for (TorrentSite torrentSite : torrentSites) {
                if (torrentSiteAliases.contains(torrentSite.getTorrentSiteAlias())) {
                    selectedTorrentSites.add(torrentSite);
                }
            }
        }
    }

    public boolean isSelected(String torrentSiteAlias) {
        for (TorrentSite torrentSite : selectedTorrentSites) {
            if (torrentSiteAlias.equals(torrentSite.getTorrentSiteAlias())) {
                return true;
            }
        }
        return false;
    }

    public String getAllSelectedSitesAsString() {
        String result = "[";
        for (TorrentSite torrentSite : selectedTorrentSites) {
            if (selectedTorrentSites.indexOf(torrentSite) != selectedTorrentSites.size() - 1) {
                result += torrentSite.getTorrentSiteAlias() + ", ";
            } else {
                result += torrentSite.getTorrentSiteAlias();
            }

        }
        result += "]";
        return result;
    }

    public void deselect(String torrentSiteAlias) {
        int index = -1;
        for (TorrentSite torrentSite : selectedTorrentSites) {
            if (torrentSiteAlias.equals(torrentSite.getTorrentSiteAlias())) {
                index = selectedTorrentSites.indexOf(torrentSite);   // can't remove it here as it will break the iterator.
            }
        }
        selectedTorrentSites.remove(index);
    }

    public List<TorrentSite> getAllTorrentSites() {
        return torrentSites;
    }

    public void select(TorrentSite torrentSite) {
        select(torrentSite.getTorrentSiteAlias());
    }

    public boolean isSelected(TorrentSite torrentSite) {
        return selectedTorrentSites.contains(torrentSite);
    }

    public void deselectAll() {
        selectedTorrentSites.clear();
    }

    public void deselect(TorrentSite torrentSite) {
        deselect(torrentSite.getTorrentSiteAlias());
    }

    public int getSelectedTorrentSitesCount() {
        return selectedTorrentSites.size();
    }

    public Torrent getATorrent(Movie movie) {
        for (TorrentSite torrentSite : selectedTorrentSites) {
            Torrent torrent = torrentSite.search(movie);
            if (torrent != null) {
                return torrent;
            }
        }
        return null;
    }

    /**
     * Used for testing purposes only! Forces an add of an invalid TorrentSite such as DummyTorrentSite
     *
     * @param torrentSite site to be added
     */
    public void forceSelect(TorrentSite torrentSite) {
        if (!torrentSites.contains(torrentSite)) {
            torrentSites.add(torrentSite);
        }
        select(torrentSite);
    }

    public void makeSureAllSelectedTorrentSitesAreConfiguredGUI() {
        for (TorrentSite torrentSite : selectedTorrentSites) {
            if (!torrentSite.isConfigured()) {
                torrentSite.configureWithGUI();
            }
        }
    }

    public void makeSureAllSelectedTorrentSitesAreConfiguredTUI() {
        for (TorrentSite torrentSite : selectedTorrentSites) {
            if (!torrentSite.isConfigured()) {
                torrentSite.configureWithTUI();
            }
        }
    }

    public boolean isConfigured(String torrentSiteAlias) {
        return getTorrentSite(torrentSiteAlias).isConfigured();
    }

    public void configureWithGUI(String torrentSiteAlias) {
        getTorrentSite(torrentSiteAlias).configureWithGUI();
    }
}
